/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package bs.facturacion.web;

import bs.entidad.modelo.EntidadComercial;
import bs.entidad.web.BuscadorEntidadBean;
import bs.facturacion.modelo.CircuitoFacturacion;
import bs.facturacion.modelo.ItemProductoFacturacion;
import bs.facturacion.modelo.MovimientoFacturacion;
import bs.facturacion.rn.CircuitoFacturacionRN;
import bs.facturacion.rn.MovimientoFacturacionRN;
import bs.facturacion.vista.PendienteFacturacionDetalle;
import bs.facturacion.vista.PendienteFacturacionGrupo;
import bs.global.excepciones.ExcepcionGeneralSistema;
import bs.global.util.JsfUtil;
import bs.seguridad.web.UsuarioSession;
import bs.stock.modelo.Producto;
import bs.stock.web.BuscadorProductoBean;
import bs.ventas.modelo.ItemImpuestoVenta;
import bs.ventas.modelo.ItemPercepcionVenta;
import bs.ventas.modelo.ItemProductoVenta;
import bs.ventas.modelo.ItemTotalVenta;
import bs.ventas.rn.ListaPrecioRN;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.faces.bean.ManagedProperty;
import org.primefaces.event.FlowEvent;

/** 
 * @author ctrosch
 */
//@ManagedBean
//@ViewScoped
public class MovimientoFacturacionBean implements Serializable {
    
    protected Logger log = Logger.getLogger(this.getClass().getName());

    protected @EJB MovimientoFacturacionRN facturacionRN;
    protected @EJB CircuitoFacturacionRN circuitoRN;
    protected @EJB ListaPrecioRN  listaPrecioRN;

    //Datos inicializacion registracion    
    protected String CIRCOM = "";    
    protected String CIRAPL = "";    
    protected String MODFC = "";    
    protected String CODFC = "";
    protected String MODVT = "";
    protected String CODVT = "";
    protected String MODST = "";
    protected String CODST = "";
    protected String MODCJ = "";
    protected String CODCJ = "";
    
    protected boolean beanIniciado = false;

    //Datos para generar movimientos aplicados
    protected List<PendienteFacturacionGrupo> movimientosPendientes;
    protected List<PendienteFacturacionDetalle> itemsPendiente;
    protected PendienteFacturacionGrupo movimientoPendiente;
    
    protected boolean seleccionaTodo;
    protected boolean seleccionaPendiente;    
    protected boolean seleccionaComprobante;    
    
    protected Map<String,String> filtroGrupo;
    protected Map<String,String> filtroDetalle;
    private Date fDesde;
    private String nrocta; 

    @ManagedProperty(value = "#{usuarioSession}")
    protected UsuarioSession usuarioSession;

    @ManagedProperty(value = "#{buscadorProductoBean}")
    protected BuscadorProductoBean buscadorProductoBean;
    
    @ManagedProperty(value = "#{buscadorEntidadBean}")
    protected BuscadorEntidadBean buscadorEntidadBean;

    protected MovimientoFacturacion m;  
    protected CircuitoFacturacion circuito;    

    
    /** Creates a new instance of MovimientoFacturacion */
    public MovimientoFacturacionBean() {

        movimientoPendiente = new PendienteFacturacionGrupo();
        itemsPendiente = new ArrayList<PendienteFacturacionDetalle>();
        filtroGrupo = new HashMap<String,String>();
        filtroDetalle = new HashMap<String,String>();
    }        
    
    public void iniciarVariables(String circom, String cirapl, String modfc, String codfc){
        
        if(!beanIniciado){
          
            CIRCOM = circom;
            CIRAPL = cirapl;
            MODFC = modfc;
            CODFC = codfc;
        
            iniciarMovimiento();    
            beanIniciado = true;
        }
    }
    
//    @PostConstruct
    public void iniciarMovimiento(){
                
        try {            
            
            if (CIRCOM != null && CIRAPL != null) {
                circuito = circuitoRN.getCircuito(CIRCOM, CIRAPL);
            }            
            if (circuito == null) {
                JsfUtil.addErrorMessage("No se encontró circuito "+ CIRCOM + "-"+CIRAPL);
                return;
            }  
            
            seleccionaPendiente = (!CIRCOM.equals(CIRAPL));            
                        
            if (circuito.getActualizaFacturacion().equals("S")&& MODFC!=null && CODFC!=null) {
                
                circuito.setComprobanteFacturacion(circuitoRN.getComprobanteFacturacion(CIRCOM, CIRAPL, MODFC, CODFC));                    
                
            }else if(circuito.getActualizaVenta().equals("S")&& MODVT!=null && CODVT!=null){
                    
                circuito.setComprobanteVenta(circuitoRN.getComprobanteVenta(CIRCOM, CIRAPL, MODVT, CODVT));                    

                if (circuito.getActualizaTesoreria().equals("S")&& MODCJ!=null && CODCJ!=null){
                    circuito.setComprobanteTesoreria(circuitoRN.getComprobanteTesoreria(CIRCOM, CIRAPL, MODCJ, CODCJ));                    
                }

                if (circuito.getActualizaStock().equals("S")&& MODST!=null && CODST!=null){
                    circuito.setComprobanteStock(circuitoRN.getComprobanteStock(CIRCOM, CIRAPL, MODST, CODST));                    
                }                                    
                
            }else if(circuito.getActualizaStock().equals("S")&& MODST!=null && CODST!=null){                    
                
                circuito.setComprobanteStock(circuitoRN.getComprobanteStock(CIRCOM, CIRAPL, MODST, CODST));                    
            }
            
            if(seleccionaPendiente){                
                filtroGrupo.put("circom = ", "'"+CIRAPL+"'");           
            }else{
                m = facturacionRN.nuevoMovimiento(circuito);
            }            
            
        } catch (ExcepcionGeneralSistema ex) {
            
            Logger.getLogger(MovimientoFacturacionBean.class.getName()).log(Level.SEVERE, null, ex);
            JsfUtil.addErrorMessage(ex.getMessage());
        }          
    }
        
    public void nuevoMovimiento(){
        
        if(circuito==null){
            JsfUtil.addErrorMessage("El circuito no puede ser nulo");
        }
        if (CIRCOM.equals(CIRAPL)) {
            try {
                m = facturacionRN.nuevoMovimiento(circuito);
            } catch (ExcepcionGeneralSistema ex) {
                Logger.getLogger(MovimientoFacturacionBean.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            m = null;
        }
    }

    public void guardar(boolean  nuevo){

        try {
            // Primero sacamos de la lista el item vacio si es circuito de inicio
            if(!m.getItemsProducto().isEmpty()){
                if(CIRCOM.equals(CIRAPL)){
                    int indice = m.getItemsProducto().size()-1;
                    m.getItemsProducto().remove(indice);
                }
            }

            facturacionRN.guardar(m);
            JsfUtil.addInfoMessage("El documento "+m.getComprobante().getDescripcion()+"-"+m.getNumeroFormulario()+" se guardó correctamente","");

            if(nuevo){
                nuevoMovimiento();
            }

        } catch (Exception ex) {

            if(circuito.getPermiteAgregarItems().equals("S")){
                //Cargarmos un nuevo item en blanco en caso de que quieran guardar sin agregar un items
                m.getItemsProducto().add((ItemProductoFacturacion) facturacionRN.nuevoItemProducto(m));
            }
            JsfUtil.addErrorMessage(ex.getMessage());
//            ex.printStackTrace();
        }
    }

    public void agregarItem(ItemProductoFacturacion item){
        try {

            if(!puedoAgregarItem(item)) return;

            calcularImportesLinea(item);
            calcularImportes();
            item.setTodoOk(true);

            //Cargarmos un nuevo item en blanco
            m.getItemsProducto().add((ItemProductoFacturacion) facturacionRN.nuevoItemProducto(m));
            
        } catch (Exception ex) {
            ex.printStackTrace();
            JsfUtil.addErrorMessage(ex.getMessage());
        }
    }

    public void eliminarItem(ItemProductoFacturacion nItem){

        if(facturacionRN.eliminarItemProducto(m, nItem)){
            calcularImportes();
            JsfUtil.addWarningMessage("Se ha borrado el item "+ nItem.getProducto().getDescripcion()+ "");
        }else{
            JsfUtil.addWarningMessage("No se ha borrado el item "+ nItem.getProducto().getDescripcion() + "");
        }
    }

    public boolean puedoAgregarItem(ItemProductoFacturacion nItem){

        if(nItem==null){
            JsfUtil.addErrorMessage("No se ha creado el item");
            return false;
        }

        /*
        if((circuito.getTipoProductoUnico()!=null) && (m.getItemsProducto().size() > 1)){
            JsfUtil.addErrorMessage("Ha superado la cantidad máxima de items, no puede continuar agregando");
            return false;
        }*/

        if(nItem.getCantidad()==null || nItem.getCantidad().compareTo(BigDecimal.ZERO)<=0){
            JsfUtil.addErrorMessage("Ingrese un valor de cantidad válido. Mayor a 0");
            return false;
        }

        if(nItem.getProducto()==null){
            JsfUtil.addErrorMessage("Seleccione un producto para agregar al comprobante");
            return false;
        }

        return true;
    }

    public void seleccionar(MovimientoFacturacion m){
        this.m = m;
    }

    public String procesoSeleccionPendientes(FlowEvent event){

        if(event.getNewStep().equals("filtro")){
            JsfUtil.addInfoMessage("Aplique los filtros que considere");
        }

        if(event.getNewStep().equals("seleccion")){
            try {
                if(m!=null){

                    JsfUtil.addInfoMessage("El comprobante fue generado, no puede regresar al paso anterior");
                    return event.getOldStep();
                }

                seleccionarMovimientosPendientes();               

            } catch (Exception e) {
                JsfUtil.addErrorMessage(e.getMessage());
            }
        }

        if(event.getNewStep().equals("movimiento")){

            try {
                if(itemsPendiente==null){
                    JsfUtil.addErrorMessage("No existen items pendientes");
                    return event.getOldStep();
                }

                if(itemsPendiente.isEmpty()){
                    JsfUtil.addErrorMessage("No existen items pendientes");
                    return event.getOldStep();
                }

//                m = produccionRN.nuevoMovimiento(circuito);
//                aplicarDatosPorDefecto();
//                produccionRN.generarItems(m,itemsPendiente);


            } catch (Exception e) {
                e.printStackTrace();
                JsfUtil.addErrorMessage("Error al generar comprobante", e.getMessage());
                return event.getOldStep();
            }
        }
        return event.getNewStep();
    }
    
    public void seleccionarMovimientosPendientes() throws ExcepcionGeneralSistema {

        if(nrocta!=null){
            if(!nrocta.isEmpty()){
                filtroGrupo.put("nrocta = ", ""+nrocta);
            }
        }

        movimientoPendiente = new PendienteFacturacionGrupo();
        movimientosPendientes = facturacionRN.getPendienteGrupo(filtroGrupo);

        itemsPendiente = new ArrayList<PendienteFacturacionDetalle>();
        seleccionaTodo = false;

        if(movimientosPendientes==null){
            throw new ExcepcionGeneralSistema("No se encontraron movimientos pendientes");
        }else{
            JsfUtil.addInfoMessage("Seleccione un comprobante para ver los pendientes");
        }
    }
    
    public void seleccionarItemPendiente(PendienteFacturacionGrupo m, boolean muestraMensaje){

        movimientoPendiente = m;
        filtroDetalle.put("circom =", "'"+m.getCircom()+"'");
        filtroDetalle.put("nrocta =", "'"+m.getNrocta()+"'");
        
        itemsPendiente = facturacionRN.getPendienteDetalle(filtroDetalle);

        if(itemsPendiente.isEmpty()&& muestraMensaje){
            JsfUtil.addWarningMessage("No se han encontrado items pendientes");
        }
    }
    
    //Seleccionar todos los items pendientes 
    public void seleccionarTodo(){

        facturacionRN.seleccionarTodo(itemsPendiente, seleccionaTodo);
    }
    
    
    public void finalizarProcesoSeleccionPendiente(){
        try {
            if(itemsPendiente==null || itemsPendiente.isEmpty()){
                JsfUtil.addErrorMessage("No existen items pendientes");
                return;
            }
            
            m = facturacionRN.nuevoMovimiento(circuito,movimientoPendiente,itemsPendiente);
            aplicarDatosPorDefecto();            
            calcularImportes();
            
        } catch (Exception e) {                        
            JsfUtil.addErrorMessage("Error al generar comprobante", e.getMessage());      
            log.log(Level.SEVERE, "Error al generar comprobante", e);
        }
    }
    
    
    public void actualizarCantidades(ItemProductoFacturacion item){

        if (CIRCOM.equals(CIRAPL)) {
            item.setCantidadOriginal(item.getCantidad());
        }
        
        actualizarAtributos(item);
    }

    /**
    * Actualizamos los atributos de stock, por el momento solo maneja nro de serie
    * @param item
    */
    public void actualizarAtributos(ItemProductoFacturacion item){

        //item.getItemDetalle().clear();
        //FC_ItemDetalle nuevoItemDetalle = facturacionRN.nuevoItemDetalle(item);
    }

    public void procesarCliente(){
        
        if(buscadorEntidadBean.getEntidad()!=null && m!=null){            
            
            EntidadComercial e = buscadorEntidadBean.getEntidad();
            
            m.setCliente(e); 
            m.setNrodoc(e.getNrodoc());
            m.setTipoDocumento(e.getTipoDocumento());
            
            m.setProvincia(e.getProvincia());
            m.setCodigoPostal(e.getCodigoPostal());
            m.setBarrio(e.getBarrio());
            m.setDireccion(e.getDireccion());
            m.setNumero(e.getNumero());
            m.setDepartamentoPiso(e.getDepartamentoPiso());
            m.setDepartamentoNumero(e.getDepartamentoNumero());
            
            m.setCondicionDeIva(e.getCondicionDeIva());
            m.setCondicionDePago(e.getCondicionDePagoVentas());
            m.setListaDePrecio(e.getListaDePrecioVenta());
            m.setMonedaListaPrecio(e.getListaDePrecioVenta().getMoneda());
            m.setVendedor(e.getVendedor()); 
            
            if(m.getFormulario()==null){
                try {
                    facturacionRN.asignarFormulario(m);
                } catch (ExcepcionGeneralSistema ex) {
                    Logger.getLogger(MovimientoFacturacionBean.class.getName()).log(Level.SEVERE, null, ex);
                    JsfUtil.addErrorMessage(ex.getMessage());
                }
            }            
        }
    }
    
    public void procesarProducto(){
        
        if(m.getListaDePrecio()==null){
            JsfUtil.addWarningMessage("El comprobante no tiene una lista de precio asignada");
            return;
        }
        
        if(buscadorProductoBean.getProducto()!=null && m!=null){
            
            Producto p = buscadorProductoBean.getProducto();            
            ItemProductoFacturacion ip = m.getItemsProducto().get(m.getItemsProducto().size()-1);
            
            ip.setProducto(p);
            ip.setProductoOriginal(p);
            ip.setUnidadMedida(p.getUnidadDeMedida());                        
            ip.setConcepto(p.getConceptoVenta());
            ip.setPrecio(listaPrecioRN.getPrecioByProducto(m.getListaDePrecio().getCodigo(), p.getCodigo()));
            
            calcularImportes();
            
            buscadorProductoBean.limpiarProducto();
        }
    }
    
    public void calcularImportesLinea(ItemProductoFacturacion item){
                
        facturacionRN.calcularImportesLinea(item);
    }
    
    public void calcularImportes(){
        
        for(ItemProductoFacturacion ip: m.getItemsProducto()){
            calcularImportesLinea(ip);
        }
        
        m.setImpGravado0000(BigDecimal.ZERO);
        m.setImpGravado1050(BigDecimal.ZERO);
        m.setImpGravado2100(BigDecimal.ZERO);
        m.setImpGravado2700(BigDecimal.ZERO);
        
                        
        for(ItemProductoFacturacion ip: m.getItemsProducto()){
            
            if(ip.getConcepto()==null){
                continue;
            }
            
            if(ip.getConcepto().getCodigo().equals("V000")){                                        
                m.setImpGravado0000(m.getImpGravado0000().add(ip.getTotalLinea()));
            }
            
            if(ip.getConcepto().getCodigo().equals("V001")){                
                m.setImpGravado2100(m.getImpGravado2100().add(ip.getTotalLinea()));
            }
            
            if(ip.getConcepto().getCodigo().equals("V002")){                
                m.setImpGravado1050(m.getImpGravado1050().add(ip.getTotalLinea()));
            }
            
            if(ip.getConcepto().getCodigo().equals("V003")){                
                m.setImpGravado2700(m.getImpGravado2700().add(ip.getTotalLinea()));
            }
        }
        
        m.setImpIva1050(m.getImpGravado1050().multiply(new BigDecimal("0.105")));
        m.setImpIva2100(m.getImpGravado2100().multiply(new BigDecimal("0.21")));
        m.setImpIva2700(m.getImpGravado2700().multiply(new BigDecimal("0.27")));
        
        m.setImpBruto(m.getImpGravado0000().add(m.getImpGravado1050()).add(m.getImpGravado2100()).add(m.getImpGravado2700()));
                
        m.setImporteTotal(m.getImpBruto().add(m.getImpIva1050()).add(m.getImpIva2100()).add(m.getImpIva2700()));
        
    }
    
    public void imprimir(){

        try {
//            System.out.println("Nombre reporte " + m.getFormulario().getNombreReporte());
//
//            if (m.getFormulario().getNombreReporte()==null){
//                throw new ExcepcionGeneralSistema("El comprobante no tienen reporte asociado");
//            }
//
//            //JasperReport masterReport = (JasperReport) JRLoader.loadObject(getClass().getClassLoader().getResourceAsStream("/isd/produccion/reporte/"+ m.getFormulario().getNombreReporte()+".jasper"));
//            JasperReport masterReport = (JasperReport) JRLoader.loadObject(getClass().getClassLoader().getResourceAsStream( m.getFormulario().getNombreReporte()+".jasper"));
//
//            Map parameters = new HashMap();
//            parameters.put("MODFOR", m.getModfor());
//            parameters.put("CODFOR", m.getCodfor());
//            parameters.put("NROFOR", m.getNrofor());
//
//            empresaRN.cargarDatosEmpresa(parameters);
//
//            String nombreArchivo = m.getComprobante().getCodigo()+"-"+m.getNrofor();
//
//            ReportFactory reportFactory = new ReportFactory();
//            reportFactory.verReportePDF(masterReport, nombreArchivo, parameters);

        } catch (NullPointerException npe) {
            JsfUtil.addErrorMessage("No se encontró el archivo: " + m.getFormulario().getNombreReporte()+".jasper");
        } catch (Exception e){
            e.printStackTrace();
            JsfUtil.addErrorMessage("No se puede imprimir a pdf " + e.getMessage());
        }
    }

    
    //------------------------------------------------------------------------------------------------------------
    
    public String getCIRAPL() {
        return CIRAPL;
    }

    public void setCIRAPL(String CIRAPL) {
        this.CIRAPL = CIRAPL;
    }

    public String getCIRCOM() {
        return CIRCOM;
    }

    public void setCIRCOM(String CIRCOM) {
        this.CIRCOM = CIRCOM;
    }

    public String getMODFC() {
        return MODFC;
    }

    public void setMODFC(String MODFC) {
        this.MODFC = MODFC;
    }

    public String getCODFC() {
        return CODFC;
    }

    public void setCODFC(String CODFC) {
        this.CODFC = CODFC;
    }

    public String getMODVT() {
        return MODVT;
    }

    public void setMODVT(String MODVT) {
        this.MODVT = MODVT;
    }

    public String getCODVT() {
        return CODVT;
    }

    public void setCODVT(String CODVT) {
        this.CODVT = CODVT;
    }

    public String getMODST() {
        return MODST;
    }

    public void setMODST(String MODST) {
        this.MODST = MODST;
    }

    public String getCODST() {
        return CODST;
    }

    public void setCODST(String CODST) {
        this.CODST = CODST;
    }

    public String getMODCJ() {
        return MODCJ;
    }

    public void setMODCJ(String MODCJ) {
        this.MODCJ = MODCJ;
    }

    public String getCODCJ() {
        return CODCJ;
    }

    public void setCODCJ(String CODCJ) {
        this.CODCJ = CODCJ;
    }
    
    public BuscadorProductoBean getBuscadorProductoBean() {
        return buscadorProductoBean;
    }

    public void setBuscadorProductoBean(BuscadorProductoBean buscadorProductoBean) {
        this.buscadorProductoBean = buscadorProductoBean;
    }

    public CircuitoFacturacion getCircuito() {
        return circuito;
    }

    public void setCircuito(CircuitoFacturacion circuito) {
        this.circuito = circuito;
    }

    public Map<String, String> getFiltroDetalle() {
        return filtroDetalle;
    }

    public void setFiltroDetalle(Map<String, String> filtroDetalle) {
        this.filtroDetalle = filtroDetalle;
    }

    public Map<String, String> getFiltroGrupo() {
        return filtroGrupo;
    }

    public void setFiltroGrupo(Map<String, String> filtroGrupo) {
        this.filtroGrupo = filtroGrupo;
    }

    public List<PendienteFacturacionDetalle> getItemsPendiente() {
        return itemsPendiente;
    }

    public void setItemsPendiente(List<PendienteFacturacionDetalle> itemsPendiente) {
        this.itemsPendiente = itemsPendiente;
    }

    public MovimientoFacturacion getM() {
        return m;
    }

    public void setM(MovimientoFacturacion m) {
        this.m = m;
    }

    public PendienteFacturacionGrupo getMovimientoPendiente() {
        return movimientoPendiente;
    }

    public void setMovimientoPendiente(PendienteFacturacionGrupo movimientoPendiente) {
        this.movimientoPendiente = movimientoPendiente;
    }

    public List<PendienteFacturacionGrupo> getMovimientosPendientes() {
        return movimientosPendientes;
    }

    public void setMovimientosPendientes(List<PendienteFacturacionGrupo> movimientosPendientes) {
        this.movimientosPendientes = movimientosPendientes;
    }

    public boolean isSeleccionaTodo() {
        return seleccionaTodo;
    }

    public void setSeleccionaTodo(boolean seleccionarTodo) {
        this.seleccionaTodo = seleccionarTodo;
    }

    public UsuarioSession getUsuarioSession() {
        return usuarioSession;
    }

    public void setUsuarioSession(UsuarioSession usuarioSession) {
        this.usuarioSession = usuarioSession;
    }

    public BuscadorEntidadBean getBuscadorEntidadBean() {
        return buscadorEntidadBean;
    }

    public void setBuscadorEntidadBean(BuscadorEntidadBean buscadorEntidadBean) {
        this.buscadorEntidadBean = buscadorEntidadBean;
    }

    public boolean isSeleccionaPendiente() {
        return seleccionaPendiente;
    }

    public void setSeleccionaPendiente(boolean seleccionaPendiente) {
        this.seleccionaPendiente = seleccionaPendiente;
    }

    public boolean isSeleccionaComprobante() {
        return seleccionaComprobante;
    }

    public void setSeleccionaComprobante(boolean seleccionaComprobante) {
        this.seleccionaComprobante = seleccionaComprobante;
    }

    public Date getfDesde() {
        return fDesde;
    }

    public void setfDesde(Date fDesde) {
        this.fDesde = fDesde;
    }

    public String getNrocta() {
        return nrocta;
    }

    public void setNrocta(String nrocta) {
        this.nrocta = nrocta;
    }

    private void aplicarDatosPorDefecto() {
        //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
    
}
